#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

// 跨平台信号处理所需头文件
#ifdef _WIN32
#include <windows.h>
#else
#include <signal.h>
#include <unistd.h>
#endif

#define MINISQL_IMPLEMENTATION
#include "minisql.hol.h"

// 全局数据库指针，用于信号处理函数访问
static MiniSQL* g_db = NULL;

// 信号处理函数：确保退出前保存数据
#ifdef _WIN32
BOOL WINAPI ConsoleHandler(DWORD dwCtrlType) {
    if (dwCtrlType == CTRL_C_EVENT || dwCtrlType == CTRL_BREAK_EVENT) {
        if (g_db) {
            printf("\n捕获到中断，正在保存数据...\n");
            minisql_close(g_db);  // 关闭数据库，确保数据写入磁盘
        }
        printf("程序已安全退出\n");
        exit(0);
        return TRUE;
    }
    return FALSE;
}
#else
static void signal_handler(int sig) {
    if (sig == SIGINT) {  // 捕获Ctrl+C信号
        if (g_db) {
            printf("\n捕获到中断，正在保存数据...\n");
            minisql_close(g_db);  // 关闭数据库，确保数据写入磁盘
        }
        printf("程序已安全退出\n");
        exit(0);
    }
}
#endif

// 显示表结构
void show_table_structure(MiniSQL* db, const char* table_name) {
    Table* table = find_table(db, table_name);
    if (!table) {
        printf("表 %s 不存在\n", table_name);
        return;
    }

    printf("表结构: %s\n", table_name);
    printf("+----------------+----------+------------+\n");
    printf("| 列名           | 类型     | 主键       |\n");
    printf("+----------------+----------+------------+\n");
    
    for (int i = 0; i < table->column_count; i++) {
        const char* type = (table->columns[i].type == MINISQL_TYPE_INT) ? "INT" : "TEXT";
        const char* primary = table->columns[i].is_primary ? "是" : "否";
        printf("| %-14s | %-8s | %-10s |\n", 
               table->columns[i].name, type, primary);
    }
    
    printf("+----------------+----------+------------+\n");
    printf("共 %d 列，%d 行数据\n", table->column_count, table->row_count);
}

// 列出所有表
void list_tables(MiniSQL* db) {
    Table* table = db->tables;
    if (!table) {
        printf("数据库中没有表\n");
        return;
    }

    printf("数据库中的表:\n");
    printf("+----------------+\n");
    printf("| 表名           |\n");
    printf("+----------------+\n");
    
    while (table) {
        printf("| %-14s |\n", table->name);
        table = table->next;
    }
    
    printf("+----------------+\n");
}

// 主交互循环
void browse(MiniSQL* db) {
    printf("MiniSQL 浏览器 (输入 'help' 查看命令)\n");
    char* line = NULL;
    size_t len = 0;
    
    while (1) {
        printf("minisql> ");
        ssize_t read = getline(&line, &len, stdin);
        
        if (read == -1) break;  // 处理Ctrl+D退出
        
        // 去除换行符和首尾空格
        if (read > 0 && line[read-1] == '\n') {
            line[read-1] = '\0';
        }
        char* sql = line;
        while (*sql && isspace((unsigned char)*sql)) sql++;
        if (*sql == '\0') {  // 空输入直接跳过
            continue;
        }
        
        // 命令匹配（转换为小写判断，但不修改原始SQL）
        char cmd[1024];
        strncpy(cmd, sql, sizeof(cmd)-1);
        cmd[sizeof(cmd)-1] = '\0';
        for (int i = 0; cmd[i]; i++) {
            cmd[i] = tolower((unsigned char)cmd[i]);
        }
        
        // 处理内置命令
        if (strcmp(cmd, "exit") == 0 || strcmp(cmd, "quit") == 0) {
            break;
        } else if (strcmp(cmd, "help") == 0) {
            printf("可用命令:\n");
            printf("  tables           - 列出所有表\n");
            printf("  desc <表名>      - 显示表结构\n");
            printf("  直接输入SQL语句   - 执行SQL（支持SELECT/INSERT/UPDATE/DELETE等）\n");
            printf("  exit/quit        - 退出浏览器\n");
        } else if (strcmp(cmd, "tables") == 0) {
            list_tables(db);
        } else if (strstr(cmd, "desc ") == cmd) {
            char* table_name = cmd + 5;
            while (*table_name && isspace((unsigned char)*table_name)) table_name++;
            show_table_structure(db, table_name);
        } else {
            // 执行SQL语句（传入原始输入，不修改大小写）
            ResultSet* result = NULL;
            int rc = minisql_exec(db, sql, &result);
            
            if (rc != MINISQL_OK) {
                printf("错误: %s\n", minisql_errmsg(db));
            } else if (result) {
                print_result_set(result);
                minisql_free_result(result);
            } else {
                printf("命令执行成功\n");
            }
        }
    }
    
    free(line);
}

int main(int argc, char* argv[]) {
    const char* db_name;
    if (argc <= 1) {
        fprintf(stderr, "用法: %s <数据库名(不带.dat)>\n", argv[0]);
        exit(-1);
    }
    db_name = argv[1];
    
    // 初始化数据库
    g_db = minisql_open(db_name);
    if (!g_db) {
        printf("无法打开数据库: %s\n", db_name);
        return 1;
    }
    
    // 注册跨平台中断处理函数
#ifdef _WIN32
    if (!SetConsoleCtrlHandler(ConsoleHandler, TRUE)) {
        printf("警告: 无法设置控制台中断处理，Ctrl+C可能导致数据丢失\n");
    }
#else
    signal(SIGINT, signal_handler);  // 捕获Ctrl+C信号
#endif
    
    printf("\n成功打开数据库: %s\n", db_name);
    browse(g_db);
    
    // 正常退出时关闭数据库
    minisql_close(g_db);
    g_db = NULL;  // 避免信号处理函数重复关闭
    printf("已关闭数据库\n");
    return 0;
}
